﻿using MetaProperties.Core;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MetaProperties.Framework;
using System.Collections.Generic;
using System.Reflection;

namespace MetaProperties.Core.Tests
{
    using System;
    using System.ComponentModel;
    using System.Linq;

    using Rhino.Mocks;


    /// <summary>
    ///This is a test class for MetaPropertyUtilsTest and is intended
    ///to contain all MetaPropertyUtilsTest Unit Tests
    ///</summary>
    [TestClass()]
    public class MetaPropertyUtilsTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        /// <summary>
        ///A test for IsMetaProperty
        ///</summary>
        [TestMethod()]
        public void IsMetaPropertyTest()
        {
            Assert.IsTrue(MetaPropertyUtils.IsMetaProperty("TestProperty"));
            Assert.IsTrue(MetaPropertyUtils.IsMetaProperty("TestMetaProperty"));
            Assert.IsFalse(MetaPropertyUtils.IsMetaProperty("TestProperty1"));
            Assert.IsFalse(MetaPropertyUtils.IsMetaProperty("Test"));
        }

        /// <summary>
        ///A test for InitializeMetaProperty
        ///</summary>
        [TestMethod()]
        [DeploymentItem("MetaProperties.Core.dll")]
        public void InitializeMetaPropertyTest()
        {
            MockRepository mocks = new MockRepository();

            TestHost host = new TestHost();
            IMetaProperty metaProperty = mocks.DynamicMock<IMetaProperty>();

            Expect.Call(() => metaProperty.Initialize(null)).IgnoreArguments().Repeat.Once();

            mocks.ReplayAll();

            host.DataProperty = metaProperty;

            PropertyInfo propertyInfo = typeof(TestHost).GetProperty("DataProperty", BindingFlags.Public | BindingFlags.Instance);

            IMetaProperty result =
                MetaPropertyUtils_Accessor.InitializeMetaProperty(host, propertyInfo);

            Assert.AreEqual(metaProperty, result);

            mocks.VerifyAll();
        }

        private class TestHost : IMetaPropertyHost
        {
            #pragma warning disable 0067
            public event PropertyChangedEventHandler PropertyChanged;
            #pragma warning restore 0067

            public IMetaProperty GetMetaProperty(string propertyName)
            {
                throw new System.NotImplementedException();
            }

            public IEnumerable<IMetaProperty> MetaProperties
            {
                get
                {
                    throw new System.NotImplementedException();
                }
            }

            private double Private
            {
                get;
                set;
            }

            protected double Protected
            {
                get;
                set;
            }

            protected internal double ProtectedInternal
            {
                get;
                set;
            }

            internal double Internal
            {
                get;
                set;
            }

            [SetEventFilter(typeof(int))]
            public IMetaProperty DataProperty
            {
                get;
                set;
            }
        }

        /// <summary>
        ///A test for InitializeMetaProperties
        ///</summary>
        [TestMethod()]
        public void InitializeMetaPropertiesTest()
        {
            MockRepository mocks = new MockRepository();

            TestHost host = new TestHost();
            IMetaProperty metaProperty = mocks.DynamicMock<IMetaProperty>();

            Expect.Call(() => metaProperty.Initialize(null)).IgnoreArguments().Repeat.Once();

            mocks.ReplayAll();

            host.DataProperty = metaProperty;

            var actual = MetaPropertyUtils.InitializeMetaProperties(host);

            Assert.AreEqual(1, actual.Count());
            Assert.AreEqual(metaProperty, actual.First());

            mocks.VerifyAll();
        }

        /// <summary>
        ///A test for InitialiseMetaProperty
        ///</summary>
        [TestMethod()]
        [DeploymentItem("MetaProperties.Core.dll")]
        public void InitialiseMetaPropertyTest()
        {
            MockRepository mocks = new MockRepository();

            TestHost host = new TestHost();
            IMetaProperty metaProperty = mocks.DynamicMock<IMetaProperty>();

            bool actionCalled = false;

            Expect.Call(() => metaProperty.Initialize(null))
                .IgnoreArguments()
                .Do((Action<MetaPropertyConfiguration>)delegate(MetaPropertyConfiguration c)
                {
                    actionCalled = true;
                    Assert.AreEqual(1, c.Attributes.Count());
                    Assert.AreEqual(host, c.Host);
                    Assert.AreEqual("Data", c.PropertyName);
                })
                .Repeat.Once();

            mocks.ReplayAll();

            host.DataProperty = metaProperty;
            PropertyInfo propertyInfo = typeof(TestHost).GetProperty("DataProperty", BindingFlags.Public | BindingFlags.Instance);

            MetaPropertyUtils_Accessor.InitialiseMetaProperty(host, propertyInfo, metaProperty);

            Assert.IsTrue(actionCalled);

            mocks.VerifyAll();
        }

        /// <summary>
        ///A test for GetPublicProperties
        ///</summary>
        [TestMethod()]
        [DeploymentItem("MetaProperties.Core.dll")]
        public void GetPublicPropertiesTest()
        {
            TestHost host = new TestHost();

            PropertyInfo propertyInfo = typeof(TestHost).GetProperty("DataProperty", BindingFlags.Public | BindingFlags.Instance);

            var actual = MetaPropertyUtils_Accessor.GetPublicProperties(host);

            Assert.AreEqual(2, actual.Count());
            Assert.IsTrue(actual.Contains(propertyInfo));
        }

        /// <summary>
        ///A test for GetPropertyName
        ///</summary>
        [TestMethod()]
        public void GetPropertyNameTest()
        {
            Assert.AreEqual("Test", MetaPropertyUtils.GetPropertyName("TestProperty"));
            Assert.AreEqual("Test", MetaPropertyUtils.GetPropertyName("TestMetaProperty"));
            Assert.AreEqual("TestMetaProperty1", MetaPropertyUtils.GetPropertyName("TestMetaProperty1"));
            Assert.AreEqual("Test", MetaPropertyUtils.GetPropertyName("Test"));
        }
    }
}
